package gruppenkalenderProjekt.db;

import gruppenkalenderProjekt.data.Benutzer;
import gruppenkalenderProjekt.data.Kalendereintrag;
import gruppenkalenderProjekt.data.KalendereintragImpl;
import gruppenkalenderProjekt.data.Kategorie;
import java.rmi.RemoteException;
import java.sql.*;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

// <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
// #[regen=yes,id=DCE.CA28840B-BF15-8D6A-60C9-47DEA211F641]
// </editor-fold>
/** Agiert als Schnittstelle zur Kalendereintrag Tabelle der Datenbank.
 * Beinhaltet die SQL Statements zur Auslesung und Datenmanipulation.
 *
 * @author  Rathke,Thies
 * @coauthor Gruppe 2
 */
public class KalendereintragMapper {

    private static KalendereintragMapper kalendereintragMapper = null;

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.5639838B-CB06-9EDA-D79C-EC6F9381E43D]
    // </editor-fold> 
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.45F8EACD-AE70-29A5-07A2-1FE0159A65FC]
    // </editor-fold> 
    protected KalendereintragMapper() {
    }

    public static KalendereintragMapper kalendereintragMapper() {
        // Wenn noch kein Kalendereintrag-Mapper existiert wird dieser jetzt erstellt
        if (kalendereintragMapper == null) {
            kalendereintragMapper = new KalendereintragMapper();
        }
        System.out.print("KalendereintragMapper erstellt...");
        return kalendereintragMapper;
    }

    /**Methode die alle Kalendereitnraege findet und zurueck gibt
     *
     * @return e ein Vector mit allen Kalendereintraegen
     */
    public Vector<Kalendereintrag> findeAlleKalendereintraege() {
        //Ein Connection Objekt wird erstellt und Datenbankverbindung wird mitgegeben
        Connection con = DBConnection.connection();
        //Ein Vektor vom Typ Kategorie wird erstellt
        Vector<Kalendereintrag> result = new Vector<Kalendereintrag>();

        try {
            //leeres Statement erstellen
            Statement stmt = con.createStatement();
            //Neues ResultSet erstellen und Datenbankinhalt in dieser ablegen
            ResultSet rs = stmt.executeQuery(
                    "SELECT * FROM kalendereintrag ");
            // Solange weitere Datensätze im Result Set vorhanden
            while (rs.next()) {
                try {
                    //Lokales Objekt zum Zwischenspeichern erstellen
                    Kalendereintrag e = new KalendereintragImpl();
                    e.setKalendereintragID(rs.getInt("e_ID"));
                    e.setTitel(rs.getString("titel"));
                    e.setKategorie(null);
                    e.setErsteller(null);        //zwischentabelle ??
                    e.setBeschreibung(rs.getString("beschreibung"));
                    e.setOrt(rs.getString("ort"));
                    e.setStartdatum(rs.getDate("startdatum"));
                    e.setStartzeit(rs.getTime("startzeit"));
                    e.setEnddatum(rs.getDate("enddatum"));
                    e.setEndzeit(rs.getTime("endzeit"));
                    e.setKalenderID(rs.getInt("k_ID"));

                    //Rekursion falls ein Kalendereintrag vorhanden ist
                    if (rs.getInt("folgetermin") != 0) {
                        e.setFolgetermin(this.findeKalendereintragMitID(rs.getInt("folgetermin")));
                    }

                    e.setTeilnehmer(null); //??
                    e.setZeitdifferenzErinnerung(rs.getInt("zeitdifferenzerinnerung"));
                    if (rs.getInt("erinnerung") == 0) {
                        e.setErinnerung(false);
                    } else {
                        e.setErinnerung(true);
                    }
                    e.setWiederholung(rs.getInt("wiederholung"));
                    if (rs.getInt("alarm") == 0) {
                        e.setAlarm(false);
                    } else {
                        e.setAlarm(true);
                    }
                    result.addElement(e);

                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }

        return result;
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.41100491-A950-15B8-DBCD-C88FAAB2F889]
    // </editor-fold>
    /**Methode die einen Kalendereintrag mit einer ID findet und zurueck gibt
     *
     * @param e_ID die ID des Kalendereintrags
     * @return e ein Kalendereintrag Objekt
     */
    public Kalendereintrag findeKalendereintragMitID(int e_ID) {
        Connection con = DBConnection.connection();                 //DB verbindung
        try {
            Statement stmt = con.createStatement();                  //leeres Statement anlegen --> jdbc!
            ResultSet rs = stmt.executeQuery( // statement füllen und ausführen an DB
                    "SELECT * FROM kalendereintrag " +
                    "WHERE e_ID=" + e_ID);

            if (rs.next()) {
                try {
                    Kalendereintrag e = new KalendereintragImpl();
                    e.setKalendereintragID(rs.getInt("e_ID"));
                    e.setTitel(rs.getString("titel"));
                    e.setKategorie(null);
                    e.setErsteller(null);        //zwischentabelle ??
                    e.setBeschreibung(rs.getString("beschreibung"));
                    e.setOrt(rs.getString("ort"));
                    e.setStartdatum(rs.getDate("startdatum"));
                    e.setStartzeit(rs.getTime("startzeit"));
                    e.setEnddatum(rs.getDate("enddatum"));
                    e.setEndzeit(rs.getTime("endzeit"));
                    e.setKalenderID(rs.getInt("k_ID"));

                    //Rekursion falls ein Kalendereintrag vorhanden ist
                    if (rs.getInt("folgetermin") != 0) {
                        e.setFolgetermin(this.findeKalendereintragMitID(rs.getInt("folgetermin")));
                    }

                    e.setTeilnehmer(null); //??
                    e.setZeitdifferenzErinnerung(rs.getInt("zeitdifferenzerinnerung"));
                    if (rs.getInt("erinnerung") == 0) {
                        e.setErinnerung(false);
                    } else {
                        e.setErinnerung(true);
                    }
                    e.setWiederholung(rs.getInt("wiederholung"));
                    if (rs.getInt("alarm") == 0) {
                        e.setAlarm(false);
                    } else {
                        e.setAlarm(true);
                    }
                    return e;

                } catch (RemoteException ex) {
                    ex.printStackTrace();
                    return null;
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        return null;

    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.9388CACC-60E2-1F0A-2535-EBDF54D3B56B]
    // </editor-fold>
    /**Methode die einen neuen Kalendereintrag anlegt
     *
     * @param kalendereintrag der anzulegende Kalendereintrag
     * @return e ein Kalendereintrag Objekt
     */
    public Kalendereintrag insert(Kalendereintrag kalendereintrag) {

        Connection con = DBConnection.connection();         //connection holen

        try {
            Statement stmt = con.createStatement();             //neues statement anlegen

            int erinnerung, alarm;
            if (kalendereintrag.isErinnerung() == false) {
                erinnerung = 0;
            } else {
                erinnerung = 1;
            }
            if (kalendereintrag.isAlarm() == false) {
                alarm = 0;
            } else {
                alarm = 1;
            }
            int folgetermin = 0;
            if (kalendereintrag.getFolgetermin() != null) {
                folgetermin = kalendereintrag.getFolgetermin().getKalendereintragID();
            }

            stmt.executeUpdate("INSERT INTO kalendereintrag (titel, beschreibung, ort, startdatum, startzeit, enddatum, endzeit, folgetermin, alarm, erinnerung,zeitdifferenzerinnerung,wiederholung, kat_ID, k_ID) " + //einfügen des neuen objekts in db
                    "VALUES ('" +
                    kalendereintrag.getTitel() + "','" +
                    kalendereintrag.getBeschreibung() + "','" +
                    kalendereintrag.getOrt() + "','" +
                    kalendereintrag.getStartdatum() + "','" +
                    kalendereintrag.getStartzeit() + "','" +
                    kalendereintrag.getEnddatum() + "','" +
                    kalendereintrag.getEndzeit() + "','" +
                    folgetermin + "','" +
                    alarm + "','" +
                    erinnerung + "','" +
                    kalendereintrag.getZeitdifferenzErinnerung() + "','" +
                    kalendereintrag.getWiederholung()+"','"+
                    kalendereintrag.getKategorie().getKategorieID() + "','" +
                    kalendereintrag.getKalenderID() + "')");


            try {

                stmt = con.createStatement();

                ResultSet rs = stmt.executeQuery("SELECT e_ID FROM kalendereintrag WHERE kalendereintrag.titel= '" + kalendereintrag.getTitel() + "' AND kalendereintrag.beschreibung = '" + kalendereintrag.getBeschreibung() + "'AND kalendereintrag.ort ='" + kalendereintrag.getOrt() + "' AND kalendereintrag.startdatum ='" + kalendereintrag.getStartdatum() + "'AND kalendereintrag.startzeit ='" + kalendereintrag.getStartzeit() + "'AND kalendereintrag.enddatum ='" + kalendereintrag.getEnddatum() + "'AND kalendereintrag.endzeit ='" + kalendereintrag.getEndzeit() + "'AND kalendereintrag.alarm ='" + alarm + "'AND kalendereintrag.erinnerung ='" + erinnerung + "'AND kalendereintrag.zeitdifferenzerinnerung ='" + kalendereintrag.getZeitdifferenzErinnerung() + "'AND kalendereintrag.kat_ID='" + kalendereintrag.getKategorie().getKategorieID() + "'AND kalendereintrag.k_ID ='" + kalendereintrag.getKalenderID() + "'");


                if (rs.next()) { //Die ID des eben eingetragenen Eintrag holen und im Objekt speichern
                    kalendereintrag.setKalendereintragID(rs.getInt("e_ID"));
                }


                //Zwischentabelle Erstellung fuellen
                stmt = con.createStatement();
                stmt.executeUpdate("INSERT INTO erstellung (e_ID, b_ID) " + //einfügen des neuen objekts in db
                        "VALUES ('" + kalendereintrag.getKalendereintragID() +
                        "','" + kalendereintrag.getErsteller().getBenutzerID() + "')");

                //Zwischentabelle Sichtbarkeit in schleife fuellen,
                //vlt. geht es auch in einem SQL Statement ?
                for (int i = 0; i < kalendereintrag.getTeilnehmer().size(); i++) {
                    stmt = con.createStatement();
                    stmt.executeUpdate("INSERT INTO sichtbarkeit (b_ID, e_ID) " + //einfügen des neuen objekts in db
                            "VALUES ('" + kalendereintrag.getTeilnehmer().elementAt(i).getBenutzerID() +
                            "','" + kalendereintrag.getKalendereintragID() + "')");

                }
            } catch (SQLException e3) {
                e3.printStackTrace();
            }
        } catch (RemoteException ex) {
            ex.printStackTrace();
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        return kalendereintrag;

    }
    //eingefügtes Objekt wird wieder zurückgegeben

    /* 1. Alle Attribute werden in Datenbank gespeichert (ohne ID)
     * 2. Select Statement um die ID des gerade erstellten Eintrags auszulesen
     * 3. In einer Schleife die Zwischentabelle "Sichtbarkeit" füllen
     *      - Die ID des soeben erstellten Kalendereintrags mit den ID's der Benutzer verknuepfen
     *      - In einer Schleife
     * 4. PROBLEM: Wo verknuepfen wir Kalender + Kalendereintrag ?
     * 5. Kalendereintrag zurueck geben

     * */
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.4B5F3993-DA70-EA2F-95B4-866A1827E49F]
    // </editor-fold>
    /**Methode die einen Kalendereintrag loescht
     *
     * @param kalendereintrag der zu loeschende Kalendereintrag
     */
    public void delete(Kalendereintrag kalendereintrag) {
        Connection con = DBConnection.connection();

        try {
            Statement stmt = con.createStatement();

            stmt.executeUpdate("DELETE FROM kalendereintrag " +
                    "WHERE e_ID=" + kalendereintrag.getKalendereintragID());

        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**Loescht den Ersteller aus der Zwischentabelle
     *
     * @param kalendereintrag Der Kalendereintrag von dem der Ersteller geloescht werden soll
     */
    public void deleteErstellerVonKalendereintrag(Kalendereintrag kalendereintrag) {
        Connection con = DBConnection.connection();

        try {
            Statement stmt = con.createStatement();

            stmt.executeUpdate("DELETE FROM erstellung " +
                    "WHERE e_ID=" + kalendereintrag.getKalendereintragID());

        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**Loescht aus der Zwischentabelle Sichtbarkeit sowohl die e_ID wie auch die b_ID eines Kalendereintrags
     *
     * @param kalendereintrag Der Eintrag aus dem alle Teilnehmer geloescht werden sollen
     */
    public void deleteAlleTeilnehmerVonKalendereintrag(Kalendereintrag kalendereintrag) {
        Connection con = DBConnection.connection();

        try {
            Statement stmt = con.createStatement();

            stmt.executeUpdate("DELETE FROM sichtbarkeit " +
                    "WHERE e_ID=" + kalendereintrag.getKalendereintragID());

        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.B7EC2000-BCE7-93EF-4C13-8246AB250CB8]
    // </editor-fold>
    /**Methode die einen Kalendereintrag aktualisiert
     *
     * @param kalendereintrag der zu aktualisierende Kalendereintrag
     * @return e ein Kalendereintrag Objekt
     */
    public Kalendereintrag update(Kalendereintrag kalendereintrag) {
        Connection con = DBConnection.connection();
        try {
            Statement stmt = con.createStatement();

            int erinnerung, alarm;
            if (kalendereintrag.isErinnerung() == false) {
                erinnerung = 0;
            } else {
                erinnerung = 1;
            }
            if (kalendereintrag.isAlarm() == false) {
                alarm = 0;
            } else {
                alarm = 1;
            }
            int folgetermin = 0;
            if (kalendereintrag.getFolgetermin() != null) {
                folgetermin = kalendereintrag.getFolgetermin().getKalendereintragID();
            }

            stmt.executeUpdate("UPDATE kalendereintrag " +
                    "SET " +
                    "titel='" + kalendereintrag.getTitel() +
                    "',beschreibung='" + kalendereintrag.getBeschreibung() +
                    "',ort='" + kalendereintrag.getOrt() +
                    "',startdatum='" + kalendereintrag.getStartdatum() +
                    "',startzeit='" + kalendereintrag.getStartzeit() +
                    "',enddatum='" + kalendereintrag.getEnddatum() +
                    "',endzeit='" + kalendereintrag.getEndzeit() +
                    "',folgetermin='" + folgetermin +
                    "',alarm='" + alarm +
                    "',erinnerung='" + erinnerung +
                    "',zeitdifferenzerinnerung='" + kalendereintrag.getZeitdifferenzErinnerung() +
                    "',wiederholung='"+kalendereintrag.getWiederholung() +
                    "',kat_ID='" + kalendereintrag.getKategorie().getKategorieID() +
                    "',k_ID='" + kalendereintrag.getKalenderID() +
                    "' WHERE e_ID=" + kalendereintrag.getKalendereintragID());


            //Zwischentabelle komplett loeschen
            this.deleteAlleTeilnehmerVonKalendereintrag(kalendereintrag);

            //Zwischentabelle Sichtbarkeit in schleife fuellen,
            //vlt. geht es auch in einem SQL Statement ?
            for (int i = 0; i < kalendereintrag.getTeilnehmer().size(); i++) {
                stmt = con.createStatement();
                stmt.executeUpdate("INSERT INTO sichtbarkeit (b_ID, e_ID) " + //einfügen des neuen objekts in db
                        "VALUES ('" + kalendereintrag.getTeilnehmer().elementAt(i).getBenutzerID() +
                        "','" + kalendereintrag.getKalendereintragID() + "')");

            }



        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return kalendereintrag; //geändertes Objekt wird wieder zurückgegeben

    }

    /**Methode die alle Kalendereintraege eines Benutzers findet und zurueck gibt
     *
     * @param b_ID die ID des Benutzers
     * @return e ein Vector mit allen Kalendereintraegen
     */
    public Vector<Kalendereintrag> findeAlleKalendereintragVonBenutzer(int b_ID) {
        Connection con = DBConnection.connection();                 //DB verbindung
        Vector<Kalendereintrag> result = new Vector<Kalendereintrag>();
        try {
            Statement stmt = con.createStatement();                  //leeres Statement anlegen --> jdbc!
            ResultSet rs = stmt.executeQuery( // statement füllen und ausführen an DB
                    "SELECT e_ID FROM sichtbarkeit " +
                    "WHERE b_ID=" + b_ID);

            while (rs.next()) {
                result.add(this.findeKalendereintragMitID(rs.getInt("e_ID")));
            }
            return result;
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        return null;

    }

    /**Methode die alle Kalendereintraege eines Kalenders findet und zurueck gibt
     *
     * @param k_ID die ID des Kalenders
     * @return e ein Vector mit allen Kalendereintraegen
     */
    public Vector<Kalendereintrag> findeKalendereintraegeVonKalender(int k_ID) {
        //Ein Connection Objekt wird erstellt und Datenbankverbindung wird mitgegeben
        Connection con = DBConnection.connection();
        //Ein Vektor vom Typ Kategorie wird erstellt
        Vector<Kalendereintrag> result = new Vector<Kalendereintrag>();

        try {
            //leeres Statement erstellen
            Statement stmt = con.createStatement();
            //Neues ResultSet erstellen und Datenbankinhalt in dieser ablegen
            ResultSet rs = stmt.executeQuery(
                    "SELECT * FROM kalendereintrag WHERE " +
                    "k_ID = " + k_ID);
            // Solange weitere Datensätze im Result Set vorhanden
            while (rs.next()) {
                try {
                    //Lokales Objekt zum Zwischenspeichern erstellen
                    Kalendereintrag e = new KalendereintragImpl();
                    e.setKalendereintragID(rs.getInt("e_ID"));
                    e.setTitel(rs.getString("titel"));
                    e.setKategorie(null); //erledigt!
                    e.setErsteller(null); //
                    e.setBeschreibung(rs.getString("beschreibung"));
                    e.setOrt(rs.getString("ort"));
                    e.setStartdatum(rs.getDate("startdatum"));
                    e.setStartzeit(rs.getTime("startzeit"));
                    e.setEnddatum(rs.getDate("enddatum"));
                    e.setEndzeit(rs.getTime("endzeit"));
                    //Rekursion falls ein Kalendereintrag vorhanden ist
                    if (rs.getInt("folgetermin") != 0) {
                        e.setFolgetermin(this.findeKalendereintragMitID(rs.getInt("folgetermin")));
                    }
                    e.setTeilnehmer(null); //??                  
                    e.setZeitdifferenzErinnerung(rs.getInt("zeitdifferenzerinnerung"));
                    e.setWiederholung(rs.getInt("wiederholung"));
                    if (rs.getInt("erinnerung") == 0) {
                        e.setErinnerung(false);
                    } else {
                        e.setErinnerung(true);
                    }
                    if (rs.getInt("alarm") == 0) {
                        e.setAlarm(false);
                    } else {
                        e.setAlarm(true);
                    }
                    //Objekte dem Vektor hinzufügen
                    result.addElement(e);

                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }

        return result;
    }

    /**Methode die alle Kalendereintraege eines Benutzers findet und zurueck gibt
     *
     * @param b_ID die ID des Benutzers
     * @return e ein Vector mit allen Kalendereintraegen
     */
    public Vector<Kalendereintrag> findeAlleKalendereintragVonBenutzerInKalender(int b_ID, int k_ID) {
        Connection con = DBConnection.connection();                 //DB verbindung
        Vector<Kalendereintrag> result = new Vector<Kalendereintrag>();
        try {
            Statement stmt = con.createStatement();                  //leeres Statement anlegen --> jdbc!
            ResultSet rs = stmt.executeQuery( // statement füllen und ausführen an DB
                    "SELECT e_ID FROM sichtbarkeit " +
                    "WHERE b_ID=" + b_ID);

            while (rs.next()) {
                Kalendereintrag temp = this.findeKalendereintragMitID(rs.getInt("e_ID"));
                if (temp.getKalenderID() == k_ID) {
                    result.add(temp);
                }
            }
            return result;
        } catch (RemoteException ex) {
            Logger.getLogger(KalendereintragMapper.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        return null;

    }
}

